package com.example.forum.controller;

import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.config.AppConfig;
import com.example.forum.model.Article;
import com.example.forum.model.Board;
import com.example.forum.model.User;
import com.example.forum.services.IArticleService;
import com.example.forum.services.IBoardService;
import com.example.forum.services.IUserService;
import com.example.forum.utils.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description: 帖子 controller 层
 * User: DELL
 * Date: 2023-09-22
 * Time: 15:36
 */
@Api(tags = "帖子接口")
@Slf4j
@RestController
@RequestMapping("/article")
public class ArticleController {

    @Resource
    private IArticleService articleService;
    @Resource
    private IBoardService boardService;
    @Resource
    private IUserService userService;

    /**
     * 发布帖子
     *
     * @param boardId 板块id
     * @param title   帖子标题
     * @param content 帖子正文
     * @return
     */
    @ApiOperation("发布帖子")
    @PostMapping("/create")
    public AppResult create(HttpServletRequest request,
                            @ApiParam("板块id") @RequestParam("boardId") @NonNull Long boardId,
                            @ApiParam("帖子标题") @RequestParam("title") @NonNull String title,
                            @ApiParam("帖子正文") @RequestParam("content") @NonNull String content) {
        // 禁止标题中包含空格
        if (StringUtil.hasSpace(title)) {
            // 打印日志
            log.warn("检测到不合规范的帖子提交 --- 标题以空格开头,title = " + title);
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_TITLE_HAS_SPACE);
        }
        // 1.检验用户是否已禁言
        HttpSession session = request.getSession(false);
        // 这里不用检验 session 是否有效,因为已经配置了拦截器
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        if (user.getState() != 0) {
            // 打印日志
            log.warn("检测到用户在禁言状态下尝试发布帖子, user id = " + user.getId());
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_USER_BANNED);
        }
        // 2.检验板块的有效性
        Board board = boardService.selectById(boardId);
        if (board == null || board.getState() != 0) {
            // 打印日志
            log.warn(ResultCode.FAILED_BOARD_BANNED + "board id = " + board);
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_BOARD_BANNED);
        }
        // 3.封装文章对象
        Article article = new Article();
        article.setUserId(user.getId());
        article.setBoardId(boardId);
        article.setTitle(title);
        article.setContent(content);
        // 4.调用 service
        articleService.create(article);
        // 更新 session
        session.setAttribute(AppConfig.USER_SESSION_KEY, userService.selectById(user.getId()));
        // 5.返回结果
        return AppResult.success();
    }

    /**
     * 根据板块 id 查询帖子列表
     *
     * @param boardId 板块id(若不传入板块id,则返回所有帖子)
     * @return
     */
    @ApiOperation("根据版块Id查询帖⼦列表")
    @GetMapping("getAllByBoardId")
    public AppResult getAllByBoardId(@ApiParam("板块id") @RequestParam(value = "boardId", required = false) Long boardId) {
        List<Article> articles = null;
        if (boardId == null) {
            // 查询所有
            articles = articleService.selectAll();
        } else {
            // 根据板块id查询对应帖子
            articles = articleService.selectAllByBoardId(boardId);
        }
        if (articles == null) {
            articles = new ArrayList<>();
        }
        return AppResult.success(articles);
    }

    @ApiOperation("根据帖子Id查询帖⼦详情")
    @GetMapping("details")
    public AppResult getDetails(HttpServletRequest request,
                                @ApiParam("帖子id") @RequestParam("id") @NonNull Long id) {
        // 调用 service,查询
        Article article = articleService.getDetailById(id);
        if (article == null) {
            // 打印日志
            log.warn(ResultCode.FAILED_ARTICLE_NOT_EXISTS.toString());
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_ARTICLE_NOT_EXISTS);
        }
        // 将帖子的 visitCount 加一
        articleService.updateVisitCount(id);
        // 简单维护一下 article 的visitCount
        // 这里虽然可能因为多线程的原因导致不准确,但是不影响
        article.setVisitCount(article.getVisitCount() + 1);
        // 验证当前登录用户是否为帖子作者
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        if (user.getId() == article.getUserId()) {
            article.setOwn(true);
        }
        return AppResult.success(article);
    }

    /**
     * 根据帖子 id 更新帖子
     *
     * @param id
     * @param title
     * @param content
     * @return
     */
    @ApiOperation("编辑帖子")
    @PostMapping("/modify")
    public AppResult modify(HttpServletRequest request,
                            @ApiParam("帖子id") @RequestParam("id") @NonNull Long id,
                            @ApiParam("帖子标题") @RequestParam("title") @NonNull String title,
                            @ApiParam("帖子正文") @RequestParam("content") @NonNull String content) {
        // 禁止标题和正文以空格开头
        // 这里因为前端已经自动 trim 了,因此检测到以 ' ' 开头肯定是非法访问,直接禁止即可
        if (title.charAt(0) == ' ' || content.charAt(0) == ' ') {
            // 打印日志
            log.warn("检测到不合规范的帖子提交 --- 文章或正文以空格开头");
            // 返回结果
            return AppResult.fail(ResultCode.FAILED);
        }
        // 获取当前登录用户
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        // 判断当前用户的状态
        if (user.getState() != 0) {
            // 打印日志
            log.warn("检测到用户在禁言状态下尝试编辑帖子, user id = " + user.getId());
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_USER_BANNED);
        }
        // 根据帖子 id 查询帖子详情
        Article article = articleService.selectById(id);
        if (article == null) {
            // 打印日志
            log.warn("检测到用户尝试编辑不存在的帖子, article id = " + id);
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_UPDATE);
        }
        // 判断当前用户是否为帖子作者
        if (user.getId() != article.getUserId()) {
            // 打印日志
            log.warn("检测到用户尝试修改不属于其的帖子, user id = " + user.getId() + ", article id = " + id);
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_FORBIDDEN);
        }
        // 判断当前帖子状态
        if (article.getState() != 0 || article.getDeleteState() != 0) {
            // 打印日志
            log.warn("检测到用户尝试修改异常状态的帖子, user id = " + user.getId() + ", article id = " + id);
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_UPDATE);
        }
        // 调用 service
        articleService.modify(id, title, content);
        // 打印日志
        log.info(MessageFormat.format("帖⼦修改成功. article id = {0}, user id = {1}, 原标题 = {2}, 新标题 = {3}",
                id, user.getId(), article.getTitle(), title));
        return AppResult.success();
    }

    @ApiOperation("点赞帖子")
    @PostMapping("/thumbsUp")
    public AppResult thumbsUp(HttpServletRequest request,
                              @ApiParam("帖子id") @RequestParam("id") @NonNull Long id) {
        // 获取当前登录用户
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        // 检测登录用户是否为禁言状态
        if (user.getState() != 0) {
            // 打印日志
            log.warn("检测到禁言用户尝试进行点赞操作, user id = " + user.getId());
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_USER_BANNED);
        }
        // 调用 service
        articleService.updateLikeCount(id);
        // 返回结果
        return AppResult.success();
    }

    @ApiOperation("删除帖子")
    @PostMapping("delete")
    public AppResult deleteById(HttpServletRequest request,
                                @ApiParam("帖子id") @RequestParam("id") @NonNull Long id) {
        // 查看用户是否已被禁言
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        if (user.getState() != 0) {
            // 打印日志
            log.warn("检测到用户在禁言状态下尝试删除帖子,user id = " + user.getId());
            // 返回结果
            return AppResult.fail(ResultCode.FAILED_USER_BANNED);
        }
        // 验证帖子是否不存在或被删除
        Article article = articleService.selectById(id);
        if (article == null || article.getDeleteState() != 0) {
            // 打印日志
            log.warn("检测到用户尝试删除状态异常的帖子(帖子不存在或帖子早已被删除),user id = " + user.getId());
            // 返回结果
            return AppResult.fail(ResultCode.FAILED);
        }
        // 验证当前登录用户是否为帖子作者
        if (user.getId() != article.getUserId()) {
            // 打印日志
            log.warn("检测到用户尝试删除不属于其的帖子,user id = " + user.getId() + ",article id = " + article.getId());
            // 返回结果
            return AppResult.fail(ResultCode.FAILED);
        }
        // 调用 service,删除
        articleService.deleteById(id);
        // 更新 session
        session.setAttribute(AppConfig.USER_SESSION_KEY, userService.selectById(user.getId()));
        // 返回结果
        return AppResult.success();
    }

    /**
     * 根据 ⽤⼾Id 查询帖⼦列表
     * 若不传入用户id,则查询当前登录用户的帖子列表
     * 若传入用户id,则直接查询传入用户的帖子列表
     *
     * @param userId
     * @return
     */
    @ApiOperation("根据⽤⼾Id查询帖⼦列表")
    @GetMapping("getAllByUserId")
    public AppResult getAllByUserId(HttpServletRequest request,
                                    @ApiParam("用户id") @RequestParam(value = "userId", required = false) Long userId) {
        List<Article> articles = null;
        if (userId == null) {
            // 返回当前登录用户的帖子列表
            HttpSession session = request.getSession(false);
            User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
            // 调用 service 层
            articles = articleService.selectAllByUserId(user.getId());
        } else {
            // 根据传入的用户查询帖子列表
            // 先验证 userId 是否有效
            User user = userService.selectById(userId);
            if (user == null || user.getDeleteState() != 0) {
                // 打印日志
                log.warn("检测到用户尝试查询不存在或已被删除的用户的帖子列表,user id = " + userId);
                return AppResult.fail(ResultCode.FAILED);
            }
            // 调用 service 层
            articles = articleService.selectAllByUserId(userId);
        }
        return AppResult.success(articles);
    }
}
